unit SUIcq;

interface
  uses
    SUStealth, Generics.Collections;

  Type
    PICQMessage = class
      private
        m_Sender    : Cardinal;
        m_Receiver  : Cardinal;
        m_Message   : String;
        m_Timestamp : TDateTime;
    public
        class function CreateObj(SSender,SReceiver:Cardinal;Text:String):PICQMessage;

        property Sender     : Cardinal  read m_Sender;
        property Receiver   : Cardinal  read m_Receiver;
        property Text       : String    read m_Message;
        property TimeStamp  : TDateTime read m_TimeStamp;

    end;

    PICQMessageLogger = class(TList<PICQMessage>)
      private
        m_WriteLog: Boolean;
      public
        function GetbySender(UIN:Cardinal):TList<PICQMessage>;
        function GetbyReceiver(UIN:Cardinal):TList<PICQMessage>;

        property Enabled : Boolean read m_WriteLog write m_WriteLog;
    end;



    PICQ = class
      private
        m_Status  : TICQStatus;
        m_XStatus : Byte;
        m_Sender  : Cardinal;
        m_Password: String;
        m_Logs    : PICQMessageLogger;
        class var _Instance : PICQ;

        function GetStatus: TICQStatus;
        procedure SetStatus(const Value: TICQStatus);
        function SinIsConnected: Boolean;
        function GetXStatus: Byte;
        procedure SetXStatus(const Value: Byte);
        function GetPassword: String;
        function GetUser: Cardinal;
        procedure SetPassword(const Value: String);
        procedure SetUser(const Value: Cardinal);

        constructor Create;
      public
        class function GetInstance():PICQ;

        function Connect(UIN:Cardinal;Password:String):Boolean; overload;virtual;
        function Connect(UIN:Cardinal;Password:String;Timeout:Cardinal):Boolean; overload; virtual;
        function Connect():Boolean; overload; virtual;
        function Connect(Timeout:Cardinal):Boolean; overload; Virtual;
        function Disconnect:Boolean; virtual;
        function SendText(Receiver:Cardinal;Text:String):Boolean; virtual;

        property  Status    : TICQStatus          read GetStatus      write SetStatus;
        property  XStatus   : Byte                read GetXStatus     write SetXStatus;
        property  Connected : Boolean             read SinIsConnected;
        property  User      : Cardinal            read GetUser        write SetUser;
        property  Password  : String              read GetPassword    write SetPassword;
        property  Logs      : PICQMessageLogger  read m_Logs;

      protected
        procedure Event_Disconnected; virtual;
        procedure Event_Connected; virtual;
        procedure Event_IncomingMessage(Sender:Cardinal;Text:String); virtual;
        procedure Event_MessageError(Text:String); virtual;
    end;

implementation
  uses
    Windows, SysUtils;

{ PICQ }

function PICQ.Connect(UIN: Cardinal; Password: String;Timeout: Cardinal): Boolean;
var
  ticks : Cardinal;
begin
  Result := Connect(UIN,Password);
  if(Result)then
  begin
    ticks := GetTickCount + Timeout;
    while(not Connected) and (GetTickCount < ticks)do
    begin
      Script.Wait(50);
    end;
    Result := Connected;
  end;
end;

function PICQ.Connect(UIN: Cardinal; Password: String): Boolean;
begin
  Result := False;
  if(UIN <> 0) and (Trim(Password) <> '')then
  begin
    if(not Connected)then
    begin
      Result := True;
      Script.ICQ.Connect(UIN,Password);
    end;
  end;
end;

function PICQ.Connect(Timeout: Cardinal): Boolean;
begin
  Result := Connect(m_Sender,m_Password,timeout);
end;

function PICQ.Connect: Boolean;
begin
  Result := Connect(m_Sender,m_Password);
end;

constructor PICQ.Create;
begin
  m_Sender := 0;
  m_Password := '';
  m_Logs := PICQMessageLogger.Create();
  m_Logs.Enabled := False;
  m_XStatus := 0;
  m_Status  := st_Home;
end;

function PICQ.Disconnect: Boolean;
begin
  Result := False;
  if(Connected)then
  begin
    Script.ICQ.Disconnect;
    Result := True;
  end;
end;

procedure PICQ.Event_Connected;
begin
  //Virtual
end;

procedure PICQ.Event_Disconnected;
begin
  //Virtual
end;

procedure PICQ.Event_IncomingMessage(Sender: Cardinal; Text: String);
begin
  if(m_Logs.Enabled)then
  begin
    m_Logs.Add(PICQMessage.CreateObj(Sender,m_Sender,Text));
  end;
end;

procedure PICQ.Event_MessageError(Text: String);
begin
  //Virtual
end;

class function PICQ.GetInstance: PICQ;
begin
  if not Assigned(_Instance) then _Instance := PICQ.Create;
  Result := _Instance;
end;

function PICQ.GetPassword: String;
begin
  Result := m_Password;
end;

function PICQ.GetStatus: TICQStatus;
begin
  Result := m_Status;
end;

function PICQ.GetUser: Cardinal;
begin
  Result := m_Sender;
end;

function PICQ.GetXStatus: Byte;
begin
  Result := m_XStatus;
end;

function PICQ.SendText(Receiver: Cardinal; Text: String): Boolean;
begin
  Result := False;
  if(Connected)then
  begin
    Result := True;
    if(m_Logs.Enabled)then m_Logs.Add(PICQMessage.CreateObj(m_Sender,Receiver,Text));
    Script.ICQ.SendText(Receiver,Text);
  end;
end;

procedure PICQ.SetPassword(const Value: String);
begin
  m_Password := Value;
end;

procedure PICQ.SetStatus(const Value: TICQStatus);
begin
  Script.ICQ.SetStatus(Value);
  m_Status := Value;
end;

procedure PICQ.SetUser(const Value: Cardinal);
begin
  m_Sender := Value;
end;

procedure PICQ.SetXStatus(const Value: Byte);
begin
  m_XStatus := Value;
  Script.ICQ.SetXStatus(Value);
end;

function PICQ.SinIsConnected: Boolean;
begin
  Result := Script.ICQ.Connected;
end;

{ PICQMessage }

class function PICQMessage.CreateObj(SSender, SReceiver: Cardinal; Text: String): PICQMessage;
begin
  Result := PICQMessage.Create;
  Result.m_Sender := SSender;
  Result.m_Receiver := SReceiver;
  Result.m_Message := Text;
  Result.m_TimeStamp := Now;
end;

{ PICQMessageLogger }

function PICQMessageLogger.GetbyReceiver(UIN: Cardinal): TList<PICQMessage>;
var
  Msg : PICQMessage;
begin
  Result := TList<PICQMessage>.Create;
  for Msg in Self do
  begin
    if(Msg.Receiver = UIN)then Result.Add(Msg);
  end;
end;

function PICQMessageLogger.GetbySender(UIN: Cardinal): TList<PICQMessage>;
var
  Msg : PICQMessage;
begin
  Result := TList<PICQMessage>.Create;
  for Msg in Self do
  begin
    if(Msg.Sender = UIN)then Result.Add(Msg);
  end;
end;

end.
